/*
*********************************************************************************************************
*    文件名称 : main.c
*    日    期 : 2020-05-29
*    说    明 : modbus网络接口实现
*    作    者 : lpr
*    版    本 : 1.0
*********************************************************************************************************
*/
#include "main.h"
uint8_t gDATABUF[DATA_BUF_SIZE]; 
wiz_NetInfo dhcp = { .mac = {0x10, 0x0E, 0xdc, 0x00, 0xab, 0xcd},
                     .ip = {0},
                     .sn = {0},
                     .gw = {0},
                     .dns = {0, 0, 0, 0},
                     .dhcp = NETINFO_STATIC
                   };
uint8_t my_dhcp_retry = 0;
Net_state net_state;
extern uint8_t ucTCPRequestFrame[2048];   //接收寄存器
extern uint16_t ucTCPRequestLen;
extern uint8_t ucTCPResponseFrame[2048];   //发送寄存器
extern uint16_t ucTCPResponseLen;
extern uint8_t bFrameSent;   //是否进行发送响应判断
u16 time_cnt = 0;
eMBErrorCode eStatus;
int main(void)
{
    uint8_t tmp;
    uint8_t memsize[2][8] = {{2, 2, 2, 2, 2, 2, 2, 2}, {2, 2, 2, 2, 2, 2, 2, 2}};
    platform_init();
    reg_wizchip_cris_cbfunc(SPI_CrisEnter, SPI_CrisExit); //注册临界区函数
    /* Chip selection call back */
#if   _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_VDM_
    reg_wizchip_cs_cbfunc(SPI_CS_Select, SPI_CS_Deselect);//注册SPI片选信号函数
#elif _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_FDM_
    reg_wizchip_cs_cbfunc(SPI_CS_Select, SPI_CS_Deselect);  // CS must be tried with LOW.
#else
#if (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SIP_) != _WIZCHIP_IO_MODE_SIP_
#error "Unknown _WIZCHIP_IO_MODE_"
#else
    reg_wizchip_cs_cbfunc(wizchip_select, wizchip_deselect);
#endif
#endif
    /* SPI Read & Write callback function */
    reg_wizchip_spi_cbfunc(SPI_ReadByte, SPI_WriteByte);	//注册读写函数
    /* WIZCHIP SOCKET Buffer initialize */
    if (ctlwizchip(CW_INIT_WIZCHIP, (void *)memsize) == -1)
    {
        while (1);
    }
    /* PHY link status check */
    do
    {
        if(ctlwizchip(CW_GET_PHYLINK, (void *)&tmp) == -1)
        {
            printf("Unknown PHY Link stauts.\r\n");
        }
    }
    while(tmp == PHY_LINK_OFF);
    setSHAR(dhcp.mac);
    DHCP_init(SOCK_DHCP, gDATABUF);
    reg_dhcp_cbfunc(my_ip_assign, my_ip_assign, my_ip_conflict);
    do
    {
        net_state = DHCP_run();
        switch(net_state)
        {
            case DHCP_IP_ASSIGN:
            case DHCP_IP_CHANGED:
                break;
            case DHCP_IP_LEASED:
                break;
            case DHCP_FAILED:
                my_dhcp_retry++;
                if(my_dhcp_retry > MY_MAX_DHCP_RETRY)
                {
                    my_dhcp_retry = 0;
                    DHCP_stop();     
                    network_init();    
                }
                break;
            default:
                break;
        }
    }
    while(net_state != DHCP_IP_LEASED);
	eStatus = eMBTCPInit(Modbus_Ports);
	eStatus =eMBEnable();
    while(1)
    {
		time_cnt++;
		usRegInputBuf[0]++;
		usRegInputBuf[0]=usRegInputBuf[0]%5000;
		usRegInputBuf[1] = usRegHoldingBuf[0]; 
		if(time_cnt ==  1000)
		{
			time_cnt = 1;
			modbus_tcps(SOCK_Modebus,Modbus_Ports);
		}
    } 
} 

/**
  * @brief  Intialize the network information to be used in WIZCHIP
  * @retval None
  */
void network_init(void)
{
    uint8_t tmpstr[6];
    ctlnetwork(CN_SET_NETINFO, (void *)&dhcp);
    ctlnetwork(CN_GET_NETINFO, (void *)&dhcp);
    ctlwizchip(CW_GET_ID, (void *)tmpstr);
}
void my_ip_assign(void)
{
    getIPfromDHCP(dhcp.ip);
    getGWfromDHCP(dhcp.gw);
    getSNfromDHCP(dhcp.sn);
    getDNSfromDHCP(dhcp.dns);
    dhcp.dhcp = NETINFO_DHCP;
    /* Network initialization */
    network_init();      // apply from dhcp
}
void my_ip_conflict(void)
{
    printf("CONFLICT IP from DHCP\r\n");
    //halt or reset or any...
    while(1); // this example is halt.
}
/**
  * @brief  Loopback Test Example Code using ioLibrary_BSD
  * @retval None
  */
int32_t loopback_tcps(uint8_t sn, uint8_t *buf, uint16_t port)
{
    int32_t ret;
    uint16_t size = 0, sentsize = 0;
    switch(getSn_SR(sn))
    {
        case SOCK_ESTABLISHED :
            if(getSn_IR(sn) & Sn_IR_CON)
            {
                printf("%d:Connected\r\n", sn);
                setSn_IR(sn, Sn_IR_CON);
            }
            if((size = getSn_RX_RSR(sn)) > 0)
            {
                if(size > DATA_BUF_SIZE)
                {
                    size = DATA_BUF_SIZE;
                }
                ret = recv(sn, buf, size);
                if(ret <= 0)
                {
                    return ret;
                }
                sentsize = 0;
                while(size != sentsize)
                {
                    ret = send(sn, buf + sentsize, size - sentsize);
                    if(ret < 0)
                    {
                        close(sn);
                        return ret;
                    }
                    sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero.
                }
            }
            break;
        case SOCK_CLOSE_WAIT :
            printf("%d:CloseWait\r\n", sn);
            if((ret = disconnect(sn)) != SOCK_OK)
            {
                return ret;
            }
            printf("%d:Closed\r\n", sn);
            break;
        case SOCK_INIT :
            printf("%d:Listen, port [%d]\r\n", sn, port);
            if( (ret = listen(sn)) != SOCK_OK)
            {
                return ret;
            }
            break;
        case SOCK_CLOSED:
            printf("%d:LBTStart\r\n", sn);
            if((ret = socket(sn, Sn_MR_TCP, port, 0x00)) != sn)
            { return ret; }
            printf("%d:Opened\r\n", sn);
            break;
        default:
            break;
    }
    return 1;
}

/**
  * @brief  Loopback Test Example Code using ioLibrary_BSD
  * @retval None
  */
int32_t loopback_udps(uint8_t sn, uint8_t *buf, uint16_t port)
{
    int32_t  ret;
    uint16_t size, sentsize;
    uint8_t  destip[4];
    uint16_t destport;
    switch(getSn_SR(sn))
    {
        case SOCK_UDP :
            if((size = getSn_RX_RSR(sn)) > 0)
            {
                if(size > DATA_BUF_SIZE)
                {
                    size = DATA_BUF_SIZE;
                }
                ret = recvfrom(sn, buf, size, destip, (uint16_t *)&destport);
                if(ret <= 0)
                {
                    printf("%d: recvfrom error. %ld\r\n", sn, ret);
                    return ret;
                }
                size = (uint16_t) ret;
                sentsize = 0;
                while(sentsize != size)
                {
                    ret = sendto(sn, buf + sentsize, size - sentsize, destip, destport);
                    if(ret < 0)
                    {
                        printf("%d: sendto error. %ld\r\n", sn, ret);
                        return ret;
                    }
                    sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero.
                }
            }
            break;
        case SOCK_CLOSED:
            printf("%d:LBUStart\r\n", sn);
            if((ret = socket(sn, Sn_MR_UDP, port, 0x00)) != sn)
            { return ret; }
            printf("%d:Opened, port [%d]\r\n", sn, port);
            break;
        default :
            break;
    }
    return 1;
}

/**
  * @brief  Loopback Test Example Code using ioLibrary_BSD
  * @retval None
  */
void platform_init(void)
{
    SystemInit();//系统时钟初始化
    USART_Configuration();//串口1初始化
    //Config SPI
    SPI_Configuration();
    //延时初始化
    delay_init();
    GPIO_ResetBits(GPIOC, GPIO_Pin_8);
    delay_ms(10);
    GPIO_SetBits(GPIOC, GPIO_Pin_8);
}
void modbus_tcps(uint8_t sn, uint16_t port)
{
    switch(getSn_SR(sn))    //获取socket状态
    {
        case SOCK_CLOSED:     //socket处于关闭状态
            socket(sn, Sn_MR_TCP, port, 0x00); //打开socket
            break;
        case SOCK_INIT :  //socket处于已经初始化状态
            listen(sn);  //监听
        case SOCK_ESTABLISHED :   //socket处于连接状态
            if(getSn_IR(sn) & Sn_IR_CON)
            {
                setSn_IR(sn, Sn_IR_CON);
            }
            ucTCPRequestLen = getSn_RX_RSR(sn); //获取接收数据长度
            if(ucTCPRequestLen > 0)
            {
                recv(sn, ucTCPRequestFrame, ucTCPRequestLen); //W5500接收数据
                xMBPortEventPost(EV_FRAME_RECEIVED);  //发送EV_FRAME_RECEIVED事件，以驱动eMBpoll()函数中的状态机
                eMBPoll();   //处理EV_FRAME_RECEIVED事件
                eMBPoll();   //处理EV_EXECUTE事件
                if(bFrameSent)
                {
                    bFrameSent = FALSE;
                    //W5500发送Modbus应答数据包
                    send(sn, ucTCPResponseFrame, ucTCPResponseLen);
                }
            }
            break;
        case SOCK_CLOSE_WAIT :   //socket处于等待关闭状态
            disconnect(sn); //关闭连接
            break;
        default:
            break;
    }
}
/*********************************END OF FILE**********************************/
